package com.yxsk.relay.job.component.endpoint.log.logger;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.UnsynchronizedAppenderBase;
import com.yxsk.relay.job.component.endpoint.context.RelayJobNetContextHolder;
import com.yxsk.relay.job.component.endpoint.log.stream.LogStream;
import lombok.experimental.UtilityClass;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;

/**
 * @Author 11376
 * @CreaTime 2019/6/30 10:37
 * @Description
 */
@UtilityClass
public class RelayJobLoggerFactory {

    private LogStream logStream;

    private String logPattern;

    private final LogStream DEFAULT_LOG_STREAM = new LogStream() {
        @Override
        public void append(String logId, String message) {
        }

        @Override
        public List<String> read(String logId) {
            return Collections.EMPTY_LIST;
        }

        @Override
        public List<String> read(String logId, long startLine, long endLine) {
            return Collections.EMPTY_LIST;
        }

        @Override
        public List<String> read(String logId, long startLine) {
            return Collections.EMPTY_LIST;
        }

        @Override
        public long getTotalRow(String logId) {
            return 0;
        }

        @Override
        public void delete(String logId) {
        }
    };

    public void init(LogStream logStream, String logPattern) {
        RelayJobLoggerFactory.logStream = logStream;
        RelayJobLoggerFactory.logPattern = logPattern;
    }

    public Logger getLogger(Class loggerClass) {
        return getLogger(loggerClass.getName());
    }

    public Logger getLogger(String loggerName) {
        LogStream stream = logStream;
        if (stream == null) {
            stream = DEFAULT_LOG_STREAM;
        }

        ch.qos.logback.classic.Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(loggerName);

        LoggerContext context = logger.getLoggerContext();

        PatternLayoutEncoder encoder = new PatternLayoutEncoder();
        encoder.setContext(context);
        encoder.setPattern(logPattern);
        encoder.start();
        encoder.setCharset(StandardCharsets.UTF_8);

        LogStream finalStream = stream;
        final Appender appender = new UnsynchronizedAppenderBase<ILoggingEvent>() {

            @Override
            protected void append(ILoggingEvent event) {
                final byte[] encode = encoder.encode(event);

                inputLog(finalStream, new String(encode, StandardCharsets.UTF_8));
            }
        };

        appender.setContext(context);
        appender.start();
        logger.addAppender(appender);

        return logger;
    }

    private void inputLog(LogStream stream, String logMessage) {
        stream.append(RelayJobNetContextHolder.getRequestId(), logMessage);
    }

}
